#include<map>
#include<set>
#include<cmath>
#include<ctime>
#include<queue>
#include<stack>
#include<cstdio>
#include<vector>
#include<string>
#include<bitset>
#include<numeric>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include"graph.h"
using namespace std;
const int MAXN=205;
int n=1,m=0;
int edg[MAXN][MAXN];
bool anc[MAXN][MAXN];
int deg[MAXN],siz[MAXN],dad[MAXN];
bitset <MAXN> res[MAXN][MAXN];
inline void work(int x){
	deg[x]=NumberOfRoads();
	m+=deg[x];
	siz[x]=1;
}
void dfs(int x){
	deg[x]=NumberOfRoads();
	m+=deg[x];
	siz[x]=1;
	for(int i=1;i<=deg[x];i++)
	{
		if(x^1&&edg[x][i]==dad[x]){
			continue;
		}
		Move(i,2);
		if(Color()^1){
			anc[x][i]=true;
			int d=NumberOfRoads(),e=LastRoad();
			if(Color()==2){
				for(int y=x;y;y=dad[y])
				{
					if(deg[y]==d&&!edg[y][e]){
						res[x][i][y]=true;
					}
				}
				Move(e,2);
			}
			else{
				for(int y=x;y<x+siz[x];y++)
				{
					if(deg[y]==d&&!edg[y][e]){
						res[x][i][y]=true;
					}
				}
				Move(e,3);
			}
			res[x][i][x]=false;
		}
		else{
			int e=LastRoad();
			n++;
			int to=n;
			edg[x][i]=to;
			edg[to][e]=x;
			dad[to]=x;
			dfs(to);
			Move(e,3);
			siz[x]+=siz[to];
		}
	}
}
bool chk=false;
#include<random>
mt19937 rnd(time(0));
bitset <MAXN> buc[5];
int col[MAXN];
void work(int x,int ine){
	int c=col[x];
	buc[c][x]=true;
	for(int i=1;i<=deg[x];i++)
	{
		if(anc[x][i]){
			Move(i,c);
			int e=LastRoad();
			res[x][i]&=buc[Color()];
			for(int j=res[x][i]._Find_first();j<=n;j=res[x][i]._Find_next(j))
			{
				if(!res[j][e][x]){
					res[x][i][j]=false;
				}
			}
			if(res[x][i].count()==1){
				int to=res[x][i]._Find_first();
				res[to][e].reset();
				res[to][e][x]=true;
			}
			Move(e,Color());
		}
		else if(edg[x][i]^dad[x]){
			Move(i,c);
			int e=LastRoad();
			int to=edg[x][i];
			work(to,e);
		}
	}
	if(ine){
		Move(ine,c);
	}
}
int dis[MAXN][MAXN];
int ans[MAXN];
inline void floyd(){
	memset(dis,0x3f,sizeof(dis));
	for(int i=1;i<=n;i++)
	{
		dis[i][i]=0;
		for(int j=1;j<=deg[i];j++)
		{
			int to=anc[i][j]?res[i][j]._Find_first():edg[i][j];
			dis[i][to]=1;
		}
	}
	for(int k=1;k<=n;k++)
	{
		for(int i=1;i<=n;i++)
		{
			for(int j=1;j<=n;j++)
			{
				dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
			}
		}
	}
	for(int i=1;i<=n;i++)
	{
		for(int j=i+1;j<=n;j++)
		{
			ans[dis[i][j]]++;
		}
	}
}
basic_string <int> col_buc[MAXN];
void Inspect(int R){
	dfs(1);
	m>>=1;
	fill(col+1,col+1+n,1);
	bool chk=false;
	while(!chk)
	{
		col_buc[1].clear();
		col_buc[2].clear();
		col_buc[3].clear();
		for(int i=1;i<=n;i++)
		{
			col_buc[col[i]].push_back(i);
		}
		shuffle(col_buc[1].begin(),col_buc[1].end(),rnd);
		shuffle(col_buc[2].begin(),col_buc[2].end(),rnd);
		shuffle(col_buc[3].begin(),col_buc[3].end(),rnd);
		int now=1;
		for(int x:col_buc[1]+col_buc[2]+col_buc[3])
		{
			col[x]=now;
			now++;
			(now>3)&&(now=1);
		}
		buc[1].reset();
		buc[2].reset();
		buc[3].reset();
		work(1,0);
		chk=true;
		for(int i=1;i<=n;i++)
		{
			for(int j=1;j<=deg[i];j++)
			{
				if(anc[i][j]&&res[i][j].count()>1){
					chk=false;
					break;
				}
			}
			if(!chk){
				break;
			}
		}
	}
	floyd();
	for(int i=1;i<=R;i++)
	{
		Answer(i,ans[i]);
	}
}